#include "QTimeEvt.hpp"
#include "QAssert.hpp"
#include "QFPkg.hpp"
#include "QFPort.hpp"

namespace QP {

Q_DEFINE_THIS_MODULE("QTimeEvt")

std::vector<std::shared_ptr<QTimeEvt>> QF_timeEvtListHead_;


QTimeEvt::QTimeEvt(QActive * const act, int s) noexcept : QEvt(s),
                                     m_act(act),
                                     m_ctr(0U),
                                     m_interval(0U) {}

void QTimeEvt::arm_(QTimeEvtCtr const nTicks) noexcept {
  Q_REQUIRE((nTicks > 0U)       /* cannot arm with 0 ticks */
            && (m_act != nullptr) /* Active object must be provided */
            && (m_ctr == 0U)    /* must be disarmed */
            && (static_cast<int>(sig) >= Q_USER_SIG));  // valid signal

  QF_CRIT_STAT_
  QF_CRIT_ENTRY_();
  m_ctr = nTicks;
  QF_timeEvtListHead_.push_back(getSharedFromThis());
  QF_CRIT_EXIT_();
}

bool QTimeEvt::disarm(void) noexcept {
  QF_CRIT_STAT_
  QF_CRIT_ENTRY_();
  bool wasArmed;
  if (m_ctr != 0U) {  // is the time event actually armed?
    wasArmed = true;
    m_ctr = 0U;  // schedule removal from the list
  } else {       // the time event was not armed
    wasArmed = false;
  }
  QF_CRIT_EXIT_();
  return wasArmed;
}

bool QTimeEvt::rearm(QTimeEvtCtr const nTicks) noexcept {
  Q_REQUIRE((nTicks > 0U)         /* cannot rearm with 0 ticks */
            && (m_act != nullptr) /* active object must be valid */
            && (static_cast<int>(sig) >= Q_USER_SIG));  // valid signal

  QF_CRIT_STAT_
  QF_CRIT_ENTRY_();

  bool isArmed;
  if (m_ctr == 0U) {  // is this time event disarmed?
    isArmed = false;
    m_ctr = nTicks;
    QF_timeEvtListHead_.push_back(getSharedFromThis());
  } else {
    isArmed = true;
    m_ctr = nTicks;  // re-load the tick counter (shift the phasing)
  }
  QF_CRIT_EXIT_();
  return isArmed;
}

QTimeEvtCtr QTimeEvt::ctr(void) const noexcept {
  QF_CRIT_STAT_
  QF_CRIT_ENTRY_();
  QTimeEvtCtr const ret = m_ctr;
  QF_CRIT_EXIT_();
  return ret;
}
}
